home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 3.2
/
Ham Radio Version 3.2 (Chestnut CD-ROMs)(1993).ISO
/
rtty
/
tlmdc
/
serial.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-30
|
6KB
|
222 lines
#include <stdio.h>
#include <dos.h>
#include <malloc.h>
#define PIC_MASK 0x21
#define PIC_EOI 0x20
#define ERR_MSK 0x9E
/* Definitions for interrupt handling */
/* COM1 */
#define COM_DATA_1 0x3F8 /* Data received on this I/O address */
#define COM_IER_1 0x3F9 /* This register enables interrupts */
#define COM_MCR_1 0x3FC /* Control Register (signals) */
#define COM_STAT_1 0x3FD /* Status Register */
#define COM_INT_1 0xC /* 0xC handles IRQ4 or COM1 by standard */
#define INT_MASK_1 0x10 /* Mask for PIC (programmable interrupt
controller) 8259A */
/* COM2 */
#define COM_DATA_2 0x2F8 /* Data received on this I/O address */
#define COM_IER_2 0x2F9 /* This register enables interrupts */
#define COM_MCR_2 0x2FC /* Control Register (signals) */
#define COM_STAT_2 0x2FD /* Status Register */
#define COM_INT_2 0xB /* 0xB handles IRQ3 or COM2 by standard */
#define INT_MASK_2 0x8 /* Mask for PIC (programmable interrupt
controller) 8259A */
static unsigned char far *c1_buf;
static unsigned char far *c2_buf;
static unsigned asc_in_1,asc_in_2,asc_old_1,asc_old_2;
static void interrupt cdecl far int_com1();
static void interrupt cdecl far int_com2();
static void far *old_c1,far *old_c2;
/* Instat is trivial. If the ring buffer point is not the same as the
is not the same as the next read point, then you have a character
waiting */
int instat(com_port)
int com_port;
{
switch(com_port) {
case 0:{
if (asc_old_1 == asc_in_1) return 0;
else return 1;
break;
}
case 1:{
if (asc_old_2 == asc_in_2) return 0;
else return 1;
break;
}
}
}
/* If the ring buffer write pointer is not the same as the ring buffer
read pointer, then a character is in the buffer */
int rcvbyte(com_port)
int com_port;
{
int ch;
switch(com_port) {
case 0: {
if (asc_old_1 == asc_in_1) return -1;
else {
ch = c1_buf[asc_old_1];
asc_old_1 += 1;
if (asc_old_1 == 4096) asc_old_1 = 0;
return ch;
}
}
case 1: {
if (asc_old_2 == asc_in_2) return -1;
else {
ch = c2_buf[asc_old_2];
asc_old_2 += 1;
if (asc_old_2 == 4096) asc_old_2 = 0;
return ch;
}
}
}
}
/* COM1 Interrupt handler. HARDWARE DEPENDENT */
static void interrupt cdecl far int_com1(es,ds,di,si,bp,sp,bx,dx,cx,ax)
unsigned es,ds,di, si, bp, sp, bx, dx, cx, ax;
{
char ch;
_disable(); /* Disable interrupts while we move data
and pointers */
if((ch = (inp(COM_STAT_1)&ERR_MSK)) == 0) { /*If no error message */
ch = inp(COM_DATA_1); /* Get the character */
c1_buf[asc_in_1] = ch; /* Store data in circular buffer */
asc_in_1 += 1;
if (asc_in_1 == 4096) asc_in_1 = 0; /* Have we wrapped? */
} else ch = inp(COM_DATA_1); /* Get the character */
_enable(); /* Enable interrupts */
outp(PIC_EOI,0x20); /* Tell 8259A we have handled the interrupt */
}
/* COM2 Interrupt handler. HARDWARE DEPENDENT */
static void interrupt cdecl far int_com2(es,ds,di,si,bp,sp,bx,dx,cx,ax)
unsigned es,ds,di, si, bp, sp, bx, dx, cx, ax;
{
char ch;
_disable(); /* Disable interrupts while we move data
and pointers */
if((ch = (inp(COM_STAT_2)&ERR_MSK)) == 0) {/* If no error message*/
ch = inp(COM_DATA_2); /* Get the character */
c2_buf[asc_in_2] = ch; /* Store data in circular buffer */
asc_in_2 += 1;
if (asc_in_2 == 4096) asc_in_2 = 0; /* Have we wrapped? */
} else ch=inp(COM_DATA_2);
_enable(); /* Enable interrupts */
outp(PIC_EOI,0x20); /* Tell 8259A we have handled the interrupt */
}
/* 4096 character buffers are utilized, that is usually more than a screenful
of data ;-) */
void asc_enab(com_port)
int com_port;
{
char ch;
switch(com_port) {
case 0:{
asc_in_1 = asc_old_1 = 0;
if((c1_buf = (unsigned char far *)_fmalloc(4096)) == NULL) {
perror("Out of memory");
exit(0);
}
old_c1 = _dos_getvect(COM_INT_1); /* Be a friendly
ISR and save the
old vector for
restoration */
_dos_setvect(COM_INT_1,int_com1); /* Tell DOS whose got
the vector now */
outp(COM_MCR_1,0xB); /* Raise DTR and OUT2 */
outp(COM_IER_1,1); /* Interrupt enable register*/
ch = inp(PIC_MASK); /* Read the current 8259A
interrupt mask */
ch &= (0xFF^INT_MASK_1);/* Reset mask for COM1 */
outp(PIC_MASK,ch); /* Send it to the 8259A */
break;
}
case 1:{
asc_in_2 = asc_old_2 = 0;
if((c2_buf = (unsigned char far *)_fmalloc(4096)) == NULL) {
perror("Out of memory");
exit(0);
}
old_c2 = _dos_getvect(COM_INT_2); /* Be a friendly
ISR and save the
old vector for
restoration */
_dos_setvect(COM_INT_2,int_com2); /* Tell DOS whose
got the vector
now */
outp(COM_MCR_2,0xB); /* Raise DTR and OUT2 */
outp(COM_IER_2,1); /* Interrupt enable register*/
ch = inp(PIC_MASK); /* Read the current 8259A
interrupt mask */
ch &= (0xFF^INT_MASK_2);/* Reset mask for COM2 */
outp(PIC_MASK,ch); /* Send it to the 8259A */
break;
}
}
}
void asc_disab(com_port)
int com_port;
{
char ch;
switch(com_port){
case 0: {
_ffree(c1_buf); /* Free the ring buffer */
ch = inp(PIC_MASK); /* Get 8259A (PIC) Mask */
ch |= INT_MASK_1; /* Set Interrupt Mask COM1 */
outp(PIC_MASK,ch); /* Write int. mask to 8259A*/
_dos_setvect(COM_INT_1,old_c1);/* Return the vector
to its old position*/
break;
}
case 1: {
_ffree(c2_buf); /*Free the ring buffer */
ch = inp(PIC_MASK); /* Get 8259A (PIC) Mask */
ch |= INT_MASK_2; /* Set Interrupt Mask COM1 */
outp(PIC_MASK,ch); /* Write int. mask to 8259A*/
_dos_setvect(COM_INT_2,old_c2);/* Restore the old
vector */
break;
}
}
}
putcom(p,ch)
int p;
unsigned char ch;
{
unsigned char status;
switch(p) {
case 0:{
do {
status = inp(COM_STAT_1);
} while (!(status&0x20));
outp(COM_DATA_1,ch);
break;
}
case 1:{
do {
status = inp(COM_STAT_2);
} while (!(status&0x20));
outp(COM_DATA_2,ch);
break;
}
}
}